Arquitectura orientada a eventos: cuando y como adoptarla

Diagrama de flechas conectando nodos representando eventos en cadena

La arquitectura orientada a eventos (Event-Driven Architecture, EDA) es uno de los patrones más promovidos en sistemas distribuidos modernos. La idea: en vez de servicios que se llaman directamente, los servicios publican eventos cuando algo cambia, y otros servicios se suscriben a los eventos relevantes. El acoplamiento se reduce; la resiliencia mejora; nuevas piezas se enchufan sin tocar las existentes.

La realidad es más matizada. Cubrimos cuándo EDA aporta valor real, qué patrones consolidan, y qué nuevos problemas trae que muchas veces se subestiman.

El cambio de paradigma

En arquitectura síncrona REST clásica:

ServiceA → POST /orders → ServiceB
ServiceA espera respuesta
ServiceA hace algo con la respuesta

En arquitectura event-driven:

ServiceA publica evento "OrderCreated" en el broker
ServiceB recibe el evento, procesa
ServiceC también lo recibe, hace lo suyo
ServiceA no espera ni sabe quiénes consumen

La diferencia es profunda: ServiceA ya no conoce a B ni C. Mañana ServiceD puede empezar a consumir los mismos eventos sin cambiar nada en ServiceA. Eso es el desacoplamiento real.

Cuándo aporta valor

EDA brilla en escenarios concretos:

  • Múltiples consumidores del mismo evento. Una orden de compra dispara: actualización de inventario, envío de email, registro analítico, fraude check. Cada uno por separado.
  • Procesamiento asíncrono natural. El usuario hace una petición; el resultado tarda minutos en computarse. Aceptas la petición, generas un evento, y el cliente consulta resultado después.
  • Dominio reactivo a cambios externos. IoT, mercados financieros, juegos online — cosas pasan continuamente y hay que reaccionar.
  • Audit trail intrínseco. Si guardas todos los eventos, tienes la historia completa de qué pasó y cuándo, sin diseñarla aparte.
  • Equipos autónomos con boundaries claros. Cada equipo posee sus eventos; otros consumen sin pedirle permiso.

Cuándo NO compensa

A menudo se aplica EDA por defecto cuando algo más simple funcionaría mejor:

  • Workflow lineal con pocos pasos. Si A → B → C → D y nadie más se beneficia, una llamada síncrona o una orquestación tradicional es más simple.
  • Necesitas respuesta inmediata al usuario. EDA es naturalmente asíncrona; si tu UI espera resultado, vuelves a un patrón request-response sobre el broker.
  • Equipo pequeño y producto temprano. La complejidad de operación (broker, esquemas, monitorización) no se amortiza.
  • Garantías de consistencia fuerte. EDA es eventualmente consistente. Si necesitas consistencia transaccional fuerte, el patrón añade fricción.

Brokers principales

En 2023, los brokers que se ven más en producción:

  • Apache Kafka: el rey en throughput alto y persistencia larga (días o semanas de retención). Modelo de log distribuido. Operación compleja pero bien dominada.
  • RabbitMQ: más simple, foco en routing flexible (exchanges, queues), no diseñado para event sourcing pero excelente para colas tradicionales.
  • NATS: muy ligero, alta performance, apto para microservicios y edge. Streams persistentes vía JetStream.
  • AWS SNS/SQS, Google Pub/Sub, Azure Service Bus: opciones managed según tu cloud.
  • Redis Streams: si ya usas Redis, opción simple para volúmenes moderados.

La elección depende de throughput esperado, retención necesaria, y preferencia por managed vs self-host. Para casi cualquier proyecto serio nuevo, Kafka es la opción por defecto si esperas escala.

Patrones que importan

Cuatro patrones que aparecen en proyectos EDA serios:

Event Sourcing

En vez de almacenar el estado actual de las entidades, almacenas la secuencia completa de eventos que las modificaron. El estado actual se reconstruye replayando los eventos. Permite auditoría perfecta y “viajar en el tiempo” pero complica queries y migración de schema.

CQRS (Command Query Responsibility Segregation)

Separas el modelo de escritura (commands) del modelo de lectura (queries). Tras un command, los read models se actualizan asincronamente vía eventos. Optimizas cada lado independientemente.

A menudo aparece junto a Event Sourcing pero son ortogonales — puedes hacer CQRS sin event sourcing y viceversa.

Saga

Para transacciones distribuidas que cruzan múltiples servicios sin XA/2PC. La saga es una secuencia de pasos donde cada paso publica un evento; si un paso falla, se ejecutan compensating actions que revierten los anteriores.

Hay dos variantes: coreografía (cada servicio reacciona a eventos sin coordinador) y orquestación (un orquestador central guía la saga). Coreografía es más desacoplada; orquestación es más fácil de razonar.

Outbox Pattern

Para garantizar atomicidad entre escribir a tu BD y publicar un evento. Escribes el evento en una tabla outbox en la misma transacción que el cambio de estado. Un proceso aparte lee de outbox y publica al broker. Resuelve el problema de “publiqué pero la BD falló” o viceversa.

Los problemas que EDA introduce

Honestidad: EDA no es solo ventajas. Problemas reales que aparecen:

  • Debugging difícil. Una request del usuario dispara una cascada de eventos a través de N servicios. Sin distributed tracing serio (OpenTelemetry, Jaeger), debugging es pesadilla.
  • Eventual consistency. El usuario hace una acción y “se ve” segundos o minutos después. UX y comunicación deben reflejarlo.
  • Schema management. Eventos que evolucionan, consumidores con versiones distintas, compatibilidad hacia atrás. Sin disciplina (Avro, Protobuf, JSON Schema en un schema registry), todo se rompe.
  • Duplicación de eventos. Los brokers ofrecen “at least once”, no “exactly once”. Tus consumidores deben ser idempotentes.
  • Operaciones del broker. Kafka cluster es un sistema serio para operar. Backups, monitoreo, capacity planning — todo es trabajo nuevo.
  • Coste cognitivo. La forma de razonar es distinta. Onboarding más largo para devs nuevos.

Cómo empezar gradualmente

Si decides que EDA es para ti, una adopción gradual reduce riesgo:

  1. Identifica un caso obvio donde múltiples sistemas reaccionan al mismo evento (típicamente: orden de compra, registro de usuario, evento de auditoría).
  2. Empieza con un broker simple (RabbitMQ, NATS) si los volúmenes lo permiten. Kafka si esperas escala desde el inicio.
  3. Un único productor, un único consumidor al principio. Añade más cuando el patrón esté domado.
  4. Schema registry desde el primer evento — no improvises con JSON sin contrato.
  5. Tracing distribuido desde el día uno. Sin él, debugging será insoportable más adelante.

Conclusión

La arquitectura orientada a eventos es una herramienta poderosa para problemas concretos: desacoplamiento de servicios, múltiples consumidores, procesamiento asíncrono natural. Pero no es una mejora gratuita — introduce nuevos problemas operativos, cognitivos y de consistencia que conviene reconocer antes de adoptar. Aplicada con criterio en los lugares correctos, mejora arquitecturas. Aplicada por dogma, las complica innecesariamente.

Síguenos en jacar.es para más sobre arquitectura distribuida, brokers de eventos y patrones modernos.

Entradas relacionadas